#Copyright (C) Nial Peters 2012
#
#This file is part of AvoScan.
#
#AvoScan is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#AvoScan is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with AvoScan.  If not, see <http://www.gnu.org/licenses/>.
"""
The main module provides the MainFrame class which, as the 
name suggests, is the main frame in the AvoScan GUI.

It is based on the wx.Notebook, and provides tabs for 
controlling the different features of AvoScan. The actual
panels contained in the tabs are implemented in the other
modules in the gui package (e.g. manual and scanning).
"""

import wx
from avoscan.gui import scanning, manual, template_editor
from avoscan.gui.artwork import AvoscanArtProvider


class MainFrame(wx.Frame):
    """
    The main window in the AvoScan GUI. It provides different tabs
    for controlling the scanner manually and for setting up scan programs.
    """     
    def __init__(self, scanner):
        
        self.scanner = scanner
        if scanner is not None:
            #TODO - remove this and implement testing with a NullScanner class
            self.scanner.set_detach_handler(self.on_scanner_disconnect)
        wx.Frame.__init__(self, None, wx.ID_ANY, "AvoScan")
        
        art = AvoscanArtProvider()
        wx.ArtProvider.Push(art)
        self.SetIcon(art.GetIcon("Avoscan"))
        
        self.top_panel = wx.Panel(self, wx.ID_ANY)
        vsizer = wx.BoxSizer(wx.VERTICAL)
        hsizer = wx.BoxSizer(wx.HORIZONTAL)
        
        self.notebook = wx.Notebook(self.top_panel, wx.ID_ANY)
        
        #manual page must be at index 0 - see on_page_change
        self.notebook.AddPage(manual.InteractiveControlPanel(self.notebook, self.scanner), "Manual")
        self.notebook.AddPage(scanning.ScanningPanel(self.notebook, self, self.scanner), "Scanning")
        self.notebook.AddPage(template_editor.TemplateEditorPanel(self.notebook),"Templates")
        
        self.zenith_button = wx.Button(self.top_panel, wx.ID_ANY, "Reset zenith")
        
        vsizer.Add(self.notebook, 1, wx.EXPAND)
        vsizer.Add(self.zenith_button, 0, wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT | wx.ALL, border=5)
        
        hsizer.AddSpacer(5)       
        hsizer.Add(vsizer, 1, wx.EXPAND)
        hsizer.AddSpacer(5)
        
        self.top_panel.SetSizer(vsizer)
        hsizer.Fit(self)
        self.top_panel.SetAutoLayout(1)
        
        wx.EVT_BUTTON(self, self.zenith_button.GetId(), self.on_reset_zenith)
        wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.notebook.GetId(), self.on_page_change)
        self.CenterOnScreen()     
        self.Show()
        
        
    def on_reset_zenith(self, event):
        """
        Event handler for handling 'Reset zenith' button
        clicks. This closes the main frame and re-opens the 
        scanner zeroing frame.
        """
        from avoscan.gui import startup
        self.Show(False)
        startup.ScannerZeroingFrame(self.scanner)
        self.Destroy()
    
    
    def on_page_change(self, evnt):
        """
        Event handler for handling page change events (i.e. when the 
        user changes between tabs). All this method does is to update
        the position displayed on the manual control tab and update
        the templates list box on the scanning tab.
        """
        #if we have moved back to the manual control page, then sync it
        # to the current position of the scanner     
        if evnt.GetSelection() == 0:
            self.notebook.GetPage(0).sync_with_scanner()
        
        elif evnt.GetSelection() == 1:
            self.notebook.GetPage(1).update()
    
    
    def on_scanner_disconnect(self, evnt):
        """
        Event handler for handling scanner disconnect events (i.e. when the
        scanner gets unplugged). Since disconnecting the scanner is an unrecoverable
        error (for now at least), this method just issues a warning and exits the program.
        """
        self.scanner.stop()
        wx.CallAfter(wx.MessageBox, "Scanner disconnected! Check the connection to your computer.", "AvoScan", wx.ICON_ERROR)
        wx.CallAfter(self.Destroy)
        
